
package com.photoeditor.demo.model.filter;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Build;

import com.android.gpuimage.GPUImageFilter;
import com.common.base.log.DLog;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import dalvik.system.DexClassLoader;

/**
 * 滤镜资源包加载帮助类
 */
public class FilterPluginsHelper {

    private static final String TAG = FilterPluginsHelper.class.getSimpleName();

    /**
     * 加载滤镜资源包
     * 
     * @param context
     * @param path APK包路径
     * @param packageName APK包名
     * @return
     */
    public static GPUImageFilter loadFilterPlugin(Context context, String path, String packageName) {
        Resources res = getUninstallAPKInfo(context, path);
        if (res == null) {
            DLog.e(TAG, "load filter plugin resource failed, package : " + packageName);
            return null;
        }
        DexClassLoader loader = getClassLoader(context, path);
        if (loader == null) {
            DLog.e(TAG, "load filter plugin classloader failed, package : " + packageName);
            return null;
        }
        try {
            Class<?> filterClass = loader.loadClass(packageName + ".PluginFilter");
            Constructor<?> constructor = filterClass.getConstructor(Context.class, Resources.class);
            Object object = constructor.newInstance(context, res);
            return (GPUImageFilter)object;
        } catch (Throwable tr) {
            DLog.e(TAG, "", tr);
        }
        return null;

    }

    /**
     * 获得指定路径的未安装包的类加载器
     * 
     * @param context
     * @param path
     * @return
     */
    public static DexClassLoader getClassLoader(Context context, String path) {
        ApplicationInfo ai = context.getApplicationInfo();
        String nativeLibraryDir = null;
        if (Build.VERSION.SDK_INT > 8) {
            nativeLibraryDir = ai.nativeLibraryDir;
        } else {
            nativeLibraryDir = "/data/data/" + ai.packageName + "/lib/";
        }
        DexClassLoader loader = null;
        try {
            File optimizedDirectory = context.getDir("cache", Context.MODE_PRIVATE);
            loader = new DexClassLoader(path, optimizedDirectory.getAbsolutePath(),
                    nativeLibraryDir, context.getClassLoader());
        } catch (Throwable tr) {
            DLog.e(TAG, "", tr);
        }
        return loader;
    }

    /**
     * 获取指定路径的未安装包的资源引用
     * 
     * @param context
     * @param path
     * @return
     */
    public static Resources getUninstallAPKInfo(Context context, String path) {
        try {
            Class<?> class_AssetManager = Class.forName("android.content.res.AssetManager");
            Object assetMag = class_AssetManager.newInstance();
            Method method_addAssetPath = class_AssetManager.getDeclaredMethod("addAssetPath",
                    String.class);
            method_addAssetPath.invoke(assetMag, path);
            Resources res = context.getResources();
            Constructor<?> constructor_Resources = Resources.class.getConstructor(
                    class_AssetManager, res.getDisplayMetrics().getClass(), res.getConfiguration()
                            .getClass());
            res = (Resources)constructor_Resources.newInstance(assetMag, res.getDisplayMetrics(),
                    res.getConfiguration());
            return res;
        } catch (Exception e) {
            DLog.e(TAG, "", e);
            return null;
        }
    }

    /**
     * 从资源包加载滤镜Icon
     *
     * @param context
     * @param path
     * @param packageName
     * @return
     */
    public static Drawable getFilterIcon(Context context, String path, String packageName) {
        Resources resource = getUninstallAPKInfo(context, path);
        if (resource != null) {
            try {
                return resource.getDrawable(resource.getIdentifier("filter_icon", "drawable", packageName));
            } catch (Throwable tr) {
            }
        }
        return null;
    }

    public static int getInteger(Resources zipResources, String name, String packageName) {
        if (zipResources != null) {
            try {
                return zipResources.getInteger(zipResources.getIdentifier(name, "integer", packageName));
            } catch (Throwable tr) {
            }
        }
        return 0;
    }
}
